home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Diamond Collection
/
The Diamond Collection (Software Vault)(Digital Impact).ISO
/
cdr44
/
xlib06p1.zip
/
WXMAIN.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-15
|
29KB
|
1,017 lines
#include <conio.h>
#include <dos.h>
#include <mem.h>
#include "xstubs.h"
#include "xinternl.h"
/*==================================================================
XMAIN.CPP contains the basic setup variables and functions for the
XLIB package.
These routines were written initially by Themie Gouthas and
company and modified March 1995 by Victor B. Putz.
===================================================================*/
/*==================================================================
This contains variables that really belong to other functions,
but we'll define them here
===================================================================*/
int VsyncHandlerActive = 0;
int MouseRefreshFlag = 0;
int MouseVsyncHandler = 0;
int WaitingStartLow = 0;
int WaitingStartHigh = 0;
int WaitingPelPan = 0;
int VsyncPaletteStart = 0;
int VsyncPaletteCount = 0;
/*==================================================================
This block contains variable declarations for the xlib routines
===================================================================*/
BYTE InGraphics = 0; /* non zero if in X graphics mode */
int CurrXMode = 0; /* contains current X graphics mode id */
int ScrnPhysicalByteWidth = 0; /* Physical screen width in bytes */
xScreenCoord_t ScrnPhysicalPixelWidth = 0; /* Physical screen width in pixels */
xScreenCoord_t ScrnPhysicalHeight = 0; /* Physical screen height in pixels */
int ErrorValue = 0; /* Error return value */
xPageHandle_t SplitScrnOffs = 0; /* Offset in VRAM of split screen */
xScreenCoord_t SplitScrnScanLine = 0; /* Scan line split screen starts at */
/* initially. Resizing the split scrn */
/* using the other functions does not */
/* change this value */
int SplitScrnVisibleHeight = 0; /* Height of the visible portion of the*/
/* split screen. */
xPageHandle_t Page0_Offs = 0; /* Offset in VRAM of main virt. screen */
xPageHandle_t Page1_Offs = 0; /* Offset in VRAM of 2nd virt. screen */
xPageHandle_t Page2_Offs = 0; /* Offset in VRAM of 3rd virt. screen */
int ScrnLogicalByteWidth = 0; /* Virtual screen width in bytes */
xScreenCoord_t ScrnLogicalPixelWidth = 0; /* Virtual screen width in pixels */
xScreenCoord_t ScrnLogicalHeight = 0; /* Virtual screen height in pixels */
xScreenCoord_t MaxScrollX = 0; /* Max X position of physical screen */
/* within virtual screen */
xScreenCoord_t MaxScrollY = 0; /* Max Y position of physical screen */
/* within virtual screen */
int DoubleBufferActive = 0; /* Indicates whether double buffering */
/* is active */
int TrippleBufferActive = 0; /* Indicates whether tripple */
/* buffering is active */
int VisiblePageIdx = 0; /* Index number of visible page 0 or 1 */
xPageHandle_t HiddenPageOffs = 0; /* Offset of Hidden Pg | only valid */
xPageHandle_t VisiblePageOffs = 0; /* Offset of Visible Pg| for D.B. mode */
xPageHandle_t WaitingPageOffs = 0; /* Offset of Waiting Pg| for T.B. mode */
xPageHandle_t NonVisual_Offs = 0; /* Offset of first non-visible VRAM */
int StartAddressFlag = 0;
xScreenCoord_t TopClip = 0; /* Clipping rectangle */
xScreenCoord_t BottomClip = 0;
xScreenCoord_t LeftClip = 0;
xScreenCoord_t RightClip = 0;
xScreenCoord_t PhysicalStartPixelX = 0; /* Coordinates of physical (visible) */
int PhysicalStartByteX = 0; /* screen relative to the virtual */
xScreenCoord_t PhysicalStartY = 0; /* screen's U.L. corner */
unsigned char SplitScrnActive = 0;
char VsyncPaletteBuffer[ 768 ];
unsigned char * pbVGABuffer = (unsigned char *)(0xA000 << 4);
void x_set_start_addr( xScreenCoord_t, xScreenCoord_t );
/*
ZeroOutParameters() zeros out all the xlib variables.
*/
void ZeroOutParameters(
void
)
{
InGraphics = 0; /* non zero if in X graphics mode */
CurrXMode = 0; /* contains current X graphics mode id */
ScrnPhysicalByteWidth = 0; /* Physical screen width in bytes */
ScrnPhysicalPixelWidth = 0; /* Physical screen width in pixels */
ScrnPhysicalHeight = 0; /* Physical screen height in pixels */
ErrorValue = 0; /* Error return value */
SplitScrnOffs = 0; /* Offset in VRAM of split screen */
SplitScrnScanLine = 0; /* Scan line split screen starts at */
/* initially. Resizing the split scrn */
/* using the other functions does not */
/* change this value */
SplitScrnVisibleHeight = 0; /* Height of the visible portion of the*/
/* split screen. */
Page0_Offs = 0; /* Offset in VRAM of main virt. screen */
Page1_Offs = 0; /* Offset in VRAM of 2nd virt. screen */
Page2_Offs = 0; /* Offset in VRAM of 3rd virt. screen */
ScrnLogicalByteWidth = 0; /* Virtual screen width in bytes */
ScrnLogicalPixelWidth = 0; /* Virtual screen width in pixels */
ScrnLogicalHeight = 0; /* Virtual screen height in pixels */
MaxScrollX = 0; /* Max X position of physical screen */
/* within virtual screen */
MaxScrollY = 0; /* Max Y position of physical screen */
/* within virtual screen */
DoubleBufferActive = 0; /* Indicates whether double buffering */
/* is active */
TrippleBufferActive = 0; /* Indicates whether tripple */
/* buffering is active */
VisiblePageIdx = 0; /* Index number of visible page 0 or 1 */
HiddenPageOffs = 0; /* Offset of Hidden Pg | only valid */
VisiblePageOffs = 0; /* Offset of Visible Pg| for D.B. mode */
WaitingPageOffs = 0; /* Offset of Waiting Pg| for T.B. mode */
NonVisual_Offs = 0; /* Offset of first non-visible VRAM */
StartAddressFlag = 0;
TopClip = 0; /* Clipping rectangle */
BottomClip = 0;
LeftClip = 0;
RightClip = 0;
PhysicalStartPixelX = 0; /* Coordinates of physical (visible) */
PhysicalStartByteX = 0; /* screen relative to the virtual */
PhysicalStartY = 0; /* screen's U.L. corner */
for ( int i = 0; i < 768; ++i ) {
VsyncPaletteBuffer[ i ] = 0;
}
}
BYTE PelPanMask[ ] = {
0x00,
0x02,
0x04,
0x06
};
BYTE DoubleScanFlag = 0;
inline void WaitVsyncStart(
void
)
{
while( inp( INPUT_STATUS_0 ) & 0x08 );
while( !( inp( INPUT_STATUS_0 ) & 0x08 ) );
}
/*==================================================================
The following sets of arrays are the register parameters to set up
the various x modes.
===================================================================*/
struct XSetup_t {
int iWidth;
int iHeight;
int iDotClock;
int iNumRegisters;
int aiRegisterValues[];
};
XSetup_t X256Y200 = {
256,
200,
0x0e3,
8,
{
0x5f00, //horz total
0x3f01, //horz displayed
0x4202, //start horz blanking
0x9f03, //end horz blanking
0x4c04, //start h sync
0x0005, //end h sync
0x0014, //turn off dword mode
0xe317 //turn on byte mode
}
};
XSetup_t X256Y240 = {
256,
240,
0x0e3,
16,
{
0x5f00, //horz total
0x3f01, //horz displayed
0x4202, //start horz blanking
0x9f03, //end horz blanking
0x4c04, //start h sync
0x0005, //end h sync
0x0d06, //vertical total
0x3e07, //overflow (bit 8 of vertical counts)
0x4109, //cell height (2 to double-scan)
0xea10, //v sync start
0xac11, //v sync end and protect cr0-cr7
0xdf12, //vertical displayed
0x0014, //turn off dword mode
0xe715, //v blank start
0x0616, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X320Y200 = {
320,
200,
0,
2,
{
0x0014, //Turn off dword mode
0xe317 //Turn on byte mode
}
};
XSetup_t X320Y240 = {
320,
240,
0x0e3,
10,
{
0x0d06, //vertical total
0x3e07, //overflow (bit 8 of vertical counts)
0x4109, //cell height (2 to double-scan)
0xea10, //v sync start
0xac11, //v sync end and protect cr0-cr7
0xdf12, //vertical displayed
0x0014, //turn off dword mode
0xe715, //v blank start
0x0616, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X360Y200 = {
360,
200,
0x0e7,
8,
{
0x6b00, //horz total
0x5901, //horz displayed
0x5a02, //start horz blanking
0x8e03, //end horz blanking
0x5e04, //start h sync
0x8a05, //end h sync
0x0014, //turn off dword mode
0xe317 //turn on byte mode
}
};
XSetup_t X360Y240 = {
360,
240,
0x0e7,
17,
{
0x6b00, //horz total
0x5901, //horz displayed
0x5a02, //start horz blanking
0x8e03, //end horz blanking
0x5e04, //start h sync
0x8a05, //end h sync
0x0d06, //vertical total
0x3e07, //overflow (bit 8 of vertical counts)
0x4109, //cell height (2 to double-scan)
0xea10, //v sync start
0xac11, //v sync end and protect cr0-cr7
0xdf12, //vertical displayed
0x2d13, //offset;
0x0014, //turn off dword mode
0xe715, //v blank start
0x0616, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X376Y282 = {
376,
282,
0x0e7,
18,
{
0x6e00, //horz total
0x5d01, //horz displayed
0x5e02, //start horz blanking
0x9103, //end horz blanking
0x6204, //start h sync
0x8f05, //end h sync
0x6206, //vertical total
0xf007, //overflow
0x6109, //cell height
0x310f, //Unknown?-->VPutz
0x3710, //v sync start
0x8911, //v sync end and protect cr0-cr7
0x3312, //vertical displayed
0x2f13, //offset
0x0014, //turn off dword mode
0x3c15, //v blank start
0x5c16, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X256Y400 = {
256,
400,
0x0e3,
8,
{
0x5f00, //horz total
0x3f01, //horz displayed
0x4202, //start horz blanking
0x9f03, //end horz blanking
0x4c04, //start h sync
0x0005, //end h sync
0x4009, //cell height
0x0014, //turn off dword mode
0xe317 //turn on byte mode
}
};
XSetup_t X256Y480 = {
256,
480,
0x0e3,
16,
{
0x5f00, //horz total
0x3f01, //horz displayed
0x4202, //start horz blanking
0x9f03, //end horz blanking
0x4c04, //start h sync
0x0005, //end h sync
0x0d06, //vertical total
0x3e07, //overflow (bit 8 of vertical counts)
0x4009, //cell height (2 to double-scan)
0xea10, //v sync start
0xac11, //v sync end and protect cr0-cr7
0xdf12, //vertical displayed
0x0014, //turn off dword mode
0xe715, //v blank start
0x0616, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X320Y400 = {
320,
400,
0x0e3,
3,
{
0x4009, //cell height
0x0014, //turn off dword mode
0xe317 //turn on byte mode
}
};
XSetup_t X320Y480 = {
320,
480,
0x0e3,
10,
{
0x0d06, //vertical total
0x3e07, //overflow (bit 8 of vertical counts)
0x4009, //cell height (2 to double-scan)
0xea10, //v sync start
0xac11, //v sync end and protect cr0-cr7
0xdf12, //vertical displayed
0x0014, //turn off dword mode
0xe715, //v blank start
0x0616, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X360Y400 = {
360,
400,
0x0e7,
9,
{
0x6b00, //horz total
0x5901, //horz displayed
0x5a02, //start horz blanking
0x8e03, //end horz blanking
0x5e04, //start h sync
0x8a05, //end h sync
0x4009, //cell height
0x0014, //turn off dword mode
0xe317 //turn on byte mode
}
};
XSetup_t X360Y480 = {
360,
480,
0x0e7,
17,
{
0x6b00, //horz total
0x5901, //horz displayed
0x5a02, //start horz blanking
0x8e03, //end horz blanking
0x5e04, //start h sync
0x8a05, //end h sync
0x0d06, //vertical total
0x3e07, //overflow
0x4009, //cell height
0xea10, //v sync start
0xac11, //v sync end and protect cr0-cr7
0xdf12, //vertical displayed
0x2d13, //offset
0x0014, //turn off dword mode
0xe715, //v blank start
0x0616, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X360Y360 = {
360,
360,
0x0e7,
15,
{
0x6b00, //horz total
0x5901, //horz displayed
0x5a02, //start horz blanking
0x8e03, //end horz blanking
0x5e04, //start h sync
0x8a05, //end h sync
0x4009, //cell height
0x8810, //v sync start
0x8511, //v sync end and protect cr0-cr7
0x6712, //vertical displayed
0x2d13, //offset
0x0014, //turn off dword mode
0x6d15, //v blank start
0xba16, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X376Y308 = {
376,
308,
0x0e7,
18,
{
0x6e00, //horz total
0x5d01, //horz displayed
0x5e02, //start horz blanking
0x9103, //end horz blanking
0x6204, //start h sync
0x8f05, //end h sync
0x6206, //vertical total
0x0f07, //overflow
0x4009, //Unknown?-->VPutz
0x310f, //Unknown?-->VPutz
0x3710, //v sync start
0x8911, //v sync end and protect cr0-cr7
0x3312, //vertical displayed
0x2f13, //offset
0x0014, //turn off dword mode
0x3c15, //v blank start
0x5c16, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t X376Y564 = {
376,
564,
0x0e7,
18,
{
0x6e00, //horz total
0x5d01, //horz displayed
0x5e02, //start horz blanking
0x9103, //end horz blanking
0x6204, //start h sync
0x8f05, //end h sync
0x6206, //vertical total
0xf007, //overflow
0x6009, //Unknown?-->VPutz
0x310f, //Unknown?-->VPutz
0x3710, //v sync start
0x8911, //v sync end and protect cr0-cr7
0x3312, //vertical displayed
0x2f13, //offset
0x0014, //turn off dword mode
0x3c15, //v blank start
0x5c16, //v blank end
0xe317 //turn on byte mode
}
};
XSetup_t * apSetupTable[] = {
&X320Y200,
&X320Y240,
&X360Y200,
&X360Y240,
&X376Y282,
&X320Y400,
&X320Y480,
&X360Y400,
&X360Y480,
&X360Y360,
&X376Y308,
&X376Y564,
&X256Y200,
&X256Y240
};
/*==================================================================
Now begins the actual "mock xlib" routines.
===================================================================*/
/*
SetLogicalScreenWidth() sets the logical page width.
*/
void SetLogicalScreenWidth(
xScreenCoord_t iNewLogicalWidth
)
{
//first round to the last multiple of 8
iNewLogicalWidth &= ( ~0x0f );
outp( CRTC_INDEX, CRTC_OFFSET );
if ( iNewLogicalWidth < ScrnPhysicalPixelWidth ) {
iNewLogicalWidth = ScrnPhysicalPixelWidth;
}
outp( CRTC_INDEX + 1, iNewLogicalWidth / 8 );
ScrnLogicalByteWidth = iNewLogicalWidth / 4;
RightClip = iNewLogicalWidth / 4;
MaxScrollX = iNewLogicalWidth - ( iNewLogicalWidth / 4 - ScrnPhysicalByteWidth ) * 4;
ScrnLogicalPixelWidth = iNewLogicalWidth;
ScrnLogicalHeight = ( 0xffff / ScrnLogicalByteWidth );
BottomClip = ScrnLogicalHeight;
MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight;
NonVisual_Offs = ScrnLogicalByteWidth * ScrnPhysicalHeight;
}
/*
ClearVideoMemory() zeros all video memory by selecting all
planes and writing zero to the whole segment.
*/
void ClearVideoMemory(
void
)
{
outpw(SC_INDEX, ALL_PLANES);
memset( pbVGABuffer, 0x0, 0x10000);
}
#define LAST_X_MODE 13
/*
x_set_mode() sets the valid graphics mode.
*/
int x_set_mode(
int iGraphicsMode,
xScreenCoord_t iNewLogicalWidth
)
{
ZeroOutParameters();
//if we've selected an invalid mode, exit
if ( LAST_X_MODE <= iGraphicsMode ) {
InGraphics = FALSE;
return -1;
}
//set the current graphics mode flags
CurrXMode = iGraphicsMode;
InGraphics = TRUE;
if ( iGraphicsMode <= 3 ) {
DoubleScanFlag = TRUE;
}
else {
DoubleScanFlag = FALSE;
}
ClearVideoMemory();
//set base x mode
union REGS r;
r.x.eax = 0x0013;
int386(0x10, &r, &r);
outpw( SC_INDEX, 0x0604 );
outpw( SC_INDEX, 0x0100 );
//Set the dot clock scanning rate, if applicable
XSetup_t * pSetup = apSetupTable[ iGraphicsMode ];
if ( pSetup->iDotClock != 0 ) {
outp( MISC_OUTPUT, pSetup->iDotClock );
}
//Undo reset (restart sequencer)
outpw( SC_INDEX, 0x0300 );
//Reprogram the CRT controller. The VSync End register contains
//the register write-protect bit, so we save the old value, mask
//out the write-protect bit, and rewrite the value
outp( CRTC_INDEX, 0x11 );
int iTemp = inp( CRTC_INDEX + 1 );
outp( CRTC_INDEX, 0x11 );
outp( CRTC_INDEX + 1, iTemp & 0x07f );
//now that we've removed the write-protection, we reset all the
//appropriate CRT registers
for ( int i = 0; i < pSetup->iNumRegisters; ++i ) {
outpw( CRTC_INDEX, pSetup->aiRegisterValues[ i ] );
}
ClearVideoMemory();
//set screen dimensions
ScrnPhysicalPixelWidth = pSetup->iWidth;
SplitScrnScanLine = pSetup->iWidth;
ScrnPhysicalByteWidth = ScrnPhysicalPixelWidth / 4;
ScrnPhysicalHeight = pSetup->iHeight;
//our base X mode is set. Now reset the logical screen width
SetLogicalScreenWidth( iNewLogicalWidth );
// ClearVideoMemory();
return 0;
}
/*
@func Enables Read/Write access to a plane using general memory access
methods.
*/
void x_select_default_plane(
unsigned char bPlane //@parm Plane to write to
)
{
bPlane &= 0x03; //mask out so we only have 0-3 to choose from
int iTemp = 0x0100;
iTemp <<= bPlane; //set only the correct bit to 1
iTemp += MAP_MASK; //set the map mask
//Select the write plane
outpw( SC_INDEX, iTemp );
//Select the read plane
iTemp = bPlane << 8;
iTemp += READ_MAP;
outpw( GC_INDEX, iTemp );
}
/*
@func internal function called to set the split screen scan line,
used by several functions.
*/
void _ScanLineBoogie(
xScreenCoord_t wScanLine
)
{
//now play with scan line magic
if ( DoubleScanFlag ) {
wScanLine *= 2;
wScanLine -= 1;
}
WaitVsyncStart();
//disable interrupts until the controller is set up
_disable();
//output bits 0-7 of the split screen scan line
outpw( CRTC_INDEX, (( int )wScanLine << 8) + LINE_COMPARE );
//bit 4 of overflow register == bit 8 of split screen scan line (!?),
//so read the overflow register and set the appropriate bit.
outp( CRTC_INDEX, OVERFLOW );
int iPortTemp = inp( CRTC_INDEX + 1 );
iPortTemp &= ~( 0x10 ); //clear out bit 5
//now set bit 5 to bit 8 of the split screen scan line
iPortTemp |= ((( unsigned char )( wScanLine >> 8 )) & 1 ) << 4;
//and finally output that value to the port.
outp( CRTC_INDEX + 1, iPortTemp );
//unfortunately, bit 6 of max scan line register =
//bit 9 of split screen scan line... here we go again...
int iTemp = ( (int)wScanLine )& ( 0x02 << 8 );
iTemp >>= 3; //move bit 9 into bit 6 position
outp( CRTC_INDEX, MAX_SCAN_LINE );
iPortTemp = inp( CRTC_INDEX + 1 );
iPortTemp &= ~( 0x40 ); //clear out bit 6
iPortTemp |= iTemp;
outp( CRTC_INDEX, MAX_SCAN_LINE );
outp( CRTC_INDEX + 1, iPortTemp );
//enable interrupts again
_enable();
}
/*
@func x_set_splitscreen enables the split screen section at the bottom of the
physical screen; good for scores, etc.
*/
void x_set_splitscreen(
xScreenCoord_t wScanLine //@parm First scan line of the split screen on the display
)
{
if ( DoubleBufferActive ) {
ErrorValue = ERROR;
return;
}
if ( SplitScrnActive ) {
ErrorValue = ERROR;
return;
}
//turn on split screen pel pan suppression so the split screen
//isn't panned as is the non split screen portion.
//First reset the AC Index/Data toggle to index state
int iPortTemp = inp( INPUT_STATUS_0 );
//Send bit 5 to prevent screen blanking
outp( AC_INDEX, AC_MODE_CONTROL + 0x20 );
//get the current AC mode control reg
iPortTemp = inp( AC_INDEX + 1 );
//Enable split screen pel panning suppression
iPortTemp |= 0x20;
outp( AC_INDEX, iPortTemp );
//now reset parameters
PhysicalStartByteX = 0;
PhysicalStartPixelX = 0;
PhysicalStartY = 0;
SplitScrnActive = TRUE;
if ( wScanLine < 0 ) {
wScanLine = 0;
}
if ( wScanLine > ScrnPhysicalHeight ) {
wScanLine = ScrnPhysicalHeight;
}
SplitScrnScanLine = wScanLine;
_ScanLineBoogie( wScanLine );
SplitScrnVisibleHeight = ScrnPhysicalHeight - SplitScrnScanLine;
//now set all pages to begin after split screen memory
Page0_Offs = ScrnLogicalByteWidth * SplitScrnVisibleHeight;
Page1_Offs = Page0_Offs;
Page2_Offs = Page0_Offs;
VisiblePageOffs = HiddenPageOffs = Page0_Offs;
//calculate # of non-split-screen rows in video ram
int iNonSplitScreenBytes = 0xffff - Page0_Offs;
int iNonSplitScreenRows = iNonSplitScreenBytes / ScrnLogicalByteWidth;
ScrnLogicalHeight = iNonSplitScreenRows;
if ( BottomClip > ScrnLogicalHeight ) {
BottomClip = ScrnLogicalHeight;
}
MaxScrollY = ScrnLogicalHeight - SplitScrnScanLine;
x_set_start_addr( 0, 0 );
}
/*
@func Swaps visible and hidden page offsets and then
executes SetStartAddr to achieve a page flip. See <f x_set_start_addr>.
*/
void x_page_flip(
xScreenCoord_t wX, //@parm X coord of new page position
xScreenCoord_t wY //@parm Y coord of new page position
)
{
if ( DoubleBufferActive ) {
int iTemp = HiddenPageOffs;
HiddenPageOffs = VisiblePageOffs;
VisiblePageOffs = iTemp;
//simulate a XOR
if ( VisiblePageIdx & 0x01 ) {
VisiblePageIdx |= ~0x01;
}
else {
VisiblePageIdx |= 0x01;
}
}
if ( TrippleBufferActive ) {
int iTemp = HiddenPageOffs;
HiddenPageOffs = VisiblePageOffs;
VisiblePageOffs = WaitingPageOffs;
WaitingPageOffs = iTemp;
++VisiblePageIdx;
if ( VisiblePageIdx >= 3 ) {
VisiblePageIdx = 0;
}
}
x_set_start_addr( wX, wY );
}
/*
@func Sets the starting address of the physical visible page
in logical screen memory.
*/
void x_set_start_addr(
xScreenCoord_t wX, //@parm X coord of new start address
xScreenCoord_t wY //@parm Y coord of new start address
)
{
int iOffset = ScrnLogicalByteWidth * wY;
if ( DoubleBufferActive || TrippleBufferActive ) {
iOffset += VisiblePageOffs;
}
else {
iOffset += Page0_Offs;
}
PhysicalStartPixelX = wX;
PhysicalStartY = wY;
PhysicalStartByteX = wX / 4;
iOffset += PhysicalStartByteX;
int iLowAddress = ( iOffset << 8 ) + ADDR_LOW;
int iHighAddress = ( iOffset & ( 0xFF << 8 ) ) + ADDR_HIGH;
int iPelPanSetup = ( PelPanMask[ wX & 0x03 ] << 8 ) + (PEL_PANNING + 0x20);
if ( VsyncHandlerActive ) {
while ( StartAddressFlag ) {
//do nothing; wait until address flag is clear
}
//disable interrupts
_disable();
WaitingStartLow = iLowAddress;
WaitingStartHigh = iHighAddress;
WaitingPelPan = iPelPanSetup;
StartAddressFlag = 1;
//reenable interrupts
_enable();
return;
}
//wait for trailing edge of vsync pulse
while ( inp( INPUT_STATUS_0 ) & 0x01 );
//now set up the new start address
_disable();
outpw( CRTC_INDEX, iLowAddress );
outpw( CRTC_INDEX, iHighAddress );
_enable();
//now wait for vertical sync so the other page will
//be invisible when we start drawing to it
while( !( inp( INPUT_STATUS_0 ) & 0x08 ) );
_disable();
outp( AC_INDEX, iPelPanSetup & 0xff ); //lo byte
outp( AC_INDEX, iPelPanSetup >> 8 ); //hi byte
_enable();
return;
}
/*
@func hides the split screen from display.
*/
void x_hide_splitscreen(
void
)
{
if ( !SplitScrnActive || ( CurrXMode > 4 )) {
ErrorValue = ERROR;
return;
}
MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight;
SplitScrnVisibleHeight = 0;
_ScanLineBoogie( ScrnPhysicalHeight );
ErrorValue = OK;
}
/*
@func shows the split screen at its earlier position.
Only use this if SplitScrnLine hs been set, and do not use in
graphics modes above 4, since it will do nothing.
*/
void x_show_splitscreen(
void
)
{
if ( !SplitScrnActive || ( CurrXMode > 4 )) {
ErrorValue = ERROR;
return;
}
MaxScrollY = ScrnLogicalHeight - SplitScrnScanLine;
SplitScrnVisibleHeight = ScrnPhysicalHeight - SplitScrnScanLine;
_ScanLineBoogie( SplitScrnScanLine );
ErrorValue = OK;
}
/*
@func Adjusts the split screen scan line to a given value;
only to be used if split screen has been initializes; will not
function for modes above 4.
*/
void x_adjust_splitscreen(
xScreenCoord_t wScanLine //@parm New scan line to begin displaying split screen
)
{
if ( !SplitScrnActive ||
( CurrXMode > 4 ) ||
( wScanLine < SplitScrnScanLine ) ) {
ErrorValue = ERROR;
return;
}
MaxScrollY = ScrnLogicalHeight - wScanLine;
SplitScrnVisibleHeight = ScrnPhysicalHeight - wScanLine;
_ScanLineBoogie( wScanLine );
ErrorValue = OK;
}
/*
@func enables double-buffering on the mode X vga memory.
*/
int x_set_doublebuffer(
int wPageHeight //@parm Height of each page in scan lines
)
{
if ( DoubleBufferActive ) {
ErrorValue = ERROR;
return ERROR;
}
//visible page = 0;
VisiblePageIdx = 0;
//find if we're requesting a valid page height
if ( wPageHeight > ( ScrnLogicalHeight / 2 ) ) {
wPageHeight = ScrnLogicalHeight / 2;
}
//set the new logical height
ScrnLogicalHeight = wPageHeight;
if ( BottomClip > ScrnLogicalHeight ) {
BottomClip = ScrnLogicalHeight;
}
int iPageSize = ScrnLogicalHeight * ScrnLogicalByteWidth;
VisiblePageOffs = Page0_Offs;
Page1_Offs = HiddenPageOffs = Page0_Offs + iPageSize;
NonVisual_Offs = Page1_Offs + iPageSize;
DoubleBufferActive = TRUE;
MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight - SplitScrnVisibleHeight;
ErrorValue = OK;
return OK;
}
/*
@func enables triple-buffering on the mode X vga memory screen.
*/
void x_set_tripplebuffer(
int wPageHeight
)
{
if ( DoubleBufferActive || TrippleBufferActive ) {
ErrorValue = ERROR;
return;
}
VisiblePageIdx = 0;
if ( wPageHeight > ( ScrnLogicalHeight / 3 ) ) {
wPageHeight = ScrnLogicalHeight / 3;
}
ScrnLogicalHeight = wPageHeight;
if ( BottomClip > ScrnLogicalHeight ) {
BottomClip = ScrnLogicalHeight;
}
int iPageSize = ScrnLogicalHeight * ScrnLogicalByteWidth;
VisiblePageOffs = Page0_Offs;
Page1_Offs = HiddenPageOffs = Page0_Offs + iPageSize;
Page2_Offs = WaitingPageOffs = Page1_Offs + iPageSize;
NonVisual_Offs = Page2_Offs + iPageSize;
TrippleBufferActive = TRUE;
MaxScrollY = ScrnLogicalHeight - ScrnPhysicalHeight - SplitScrnVisibleHeight;
ErrorValue = OK;
}
/*
@func sets the new clipping rectangle for selected clipping functions
*/
void x_set_cliprect(
xScreenCoord_t wLeft, //@parm left edge of clipping rectangle
xScreenCoord_t wTop, //@parm top edge of clipping rectangle
xScreenCoord_t wRight, //@parm right edge of clipping rectangle
xScreenCoord_t wBottom //@parm bottom edge of clipping rectangle
)
{
//do x...
if (wLeft > wRight) {
int wTemp = wLeft;
wLeft = wRight;
wRight = wTemp;
}
LeftClip = wLeft;
RightClip = wRight;
//...then do y.
if (wTop > wBottom) {
int wTemp = wTop;
wTop = wBottom;
wBottom = wTemp;
}
TopClip = wTop;
BottomClip = wBottom;
}
/*
@func x_text_mode simply returns the user to 80x25 mode
*/
void x_text_mode(
void
)
{
ClearVideoMemory();
union REGS r;
r.x.eax = 0x0003;
int386(0x10, &r, &r);
}
/*
@func Waits for the vertical refresh to end
*/
void x_wait_vsync(
void
)
{
WaitVsyncStart();
}